package com.fanix5.javamvvm.base;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

public abstract class MvvmBaseFragment<DB extends ViewDataBinding, VM extends BaseViewModel> extends Fragment {


    protected DB mDatabind;

    protected VM mViewModel;
    private int viewModelId;

    /**
     * 日志输出标志
     */
    protected String TAG = this.getClass().getSimpleName();
    protected View rootView = null;


    /**
     * 布局是否创建完成
     */
    protected boolean isViewCreated = false;

    /**
     * 当前可见状态
     */
    protected boolean currentVisibleState = false;

    /**
     * 是否第一次可见
     */
    protected boolean mIsFirstVisible = true;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate: ");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (rootView == null) {
            mDatabind = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
            rootView = mDatabind.getRoot();
        }
        isViewCreated = true;
        return rootView;
    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);


        viewModelId = initVariableId();

        try {
            if (mViewModel == null) {
                Class modelClass;
                Type type = getClass().getGenericSuperclass();
                if (type instanceof ParameterizedType) {
                    modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[1];
                } else {
                    //如果没有指定泛型参数，则默认使用BaseViewModel
                    modelClass = BaseViewModel.class;
                }
                mViewModel = (VM) new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(modelClass);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        mDatabind.setVariable(viewModelId, mViewModel);
        mDatabind.executePendingBindings();
        mDatabind.setLifecycleOwner(this);

        initView();
        Log.e(TAG, "onViewCreated: ");
        // 初始化的时候,判断当前Fragment可见状态
        // isHidden在使用FragmentTransaction的show/hidden时会调用,可见返回的是false
        //页面事件监听的方法，一般用于ViewModel层转到View层的事件注册
        initViewObservable();
        initListener();
        if (!isHidden() && getUserVisibleHint()) {
            // 可见状态,进行事件分发
            dispatchUserVisibleHint(true);
        }


    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e(TAG, "onActivityCreated: ");
        initData();

    }




    /**
     * 第一次可见,根据业务进行初始化操作
     */
    protected void onFragmentFirstVisible() {
        Log.e(TAG, "onFragmentFirstVisible  第一次可见");
    }


    /**
     * Fragment真正的Resume,开始处理网络加载等耗时操作
     */
    protected void onFragmentResume() {
        Log.d(TAG, "onFragmentResume" + " 真正的Resume 开始相关操作耗时");
    }


    /**
     * 在双重ViewPager嵌套的情况下，第一次滑到Frgment 嵌套ViewPager(fragment)的场景的时候
     * 此时只会加载外层Fragment的数据，而不会加载内嵌viewPager中的fragment的数据，因此，我们
     * 需要在此增加一个当外层Fragment可见的时候，分发可见事件给自己内嵌的所有Fragment显示
     */
    private void dispatchChildVisibleState(boolean visible) {
        Log.d(TAG, "dispatchChildVisibleState " + visible);
        FragmentManager fragmentManager = getChildFragmentManager();
        List<Fragment> fragments = fragmentManager.getFragments();
        if (null != fragments) {
            for (Fragment fragment : fragments) {
                if (fragment instanceof MvvmBaseFragment && !fragment.isHidden()
                        && fragment.getUserVisibleHint()) {
                    ((MvvmBaseFragment) fragment).dispatchUserVisibleHint(visible);
                }
            }
        }

    }

    /**
     * Fragment真正的Pause,暂停一切网络耗时操作
     */
    protected void onFragmentPause() {
        Log.d(TAG, "onFragmentPause " + " 真正的Pause 结束相关操作耗时");

    }

    /**
     * 统一处理用户可见事件分发
     */
    private void dispatchUserVisibleHint(boolean isVisible) {
        Log.d(TAG, "dispatchUserVisibleHint: " + isVisible);

        // 首先考虑一下fragment嵌套fragment的情况(只考虑2层嵌套)
        if (isVisible && isParentInvisible()) {
            // 父Fragmnet此时不可见,直接return不做处理
            return;
        }
        // 为了代码严谨,如果当前状态与需要设置的状态本来就一致了,就不处理了
        if (currentVisibleState == isVisible) {
            return;
        }
        currentVisibleState = isVisible;
        if (isVisible) {
            if (mIsFirstVisible) {
                mIsFirstVisible = false;
                // 第一次可见,进行全局初始化
                onFragmentFirstVisible();
            }
            onFragmentResume();
            // 分发事件给内嵌的Fragment
            dispatchChildVisibleState(true);
        } else {
            onFragmentPause();
            dispatchChildVisibleState(false);
        }

    }


    /**
     * 跳转页面
     *
     * @param clz 所跳转的目的Activity类
     */
    public void startActivity(Class<?> clz) {
        startActivity(new Intent(getContext(), clz));
    }


    /**
     * 创建viewmodel
     *
     * @return
     */

    public ViewModelProvider getViewModel() {
        return new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory());
    }


    /**
     * 跳转页面
     *
     * @param clz    所跳转的目的Activity类
     * @param bundle 跳转所携带的信息
     */
    public void startActivity(Class<?> clz, Bundle bundle) {
        Intent intent = new Intent(getContext(), clz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }


    private boolean isParentInvisible() {
        Fragment parentFragment = getParentFragment();
        if (parentFragment instanceof MvvmBaseFragment) {
            MvvmBaseFragment fragment = (MvvmBaseFragment) parentFragment;
            return !fragment.isSupportVisible();
        }
        return false;
    }

    private boolean isSupportVisible() {
        return currentVisibleState;
    }


    @Override
    public void onDestroyView() {
        super.onDestroyView();


        isViewCreated = false;
        currentVisibleState = false;

        if(mDatabind != null){
            mDatabind.unbind();
        }
        if (rootView.getParent() != null) {
            ((ViewGroup) rootView.getParent()).removeView(rootView);
        }

        if(rootView != null){
            rootView = null;
        }


    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    /**
     * 获取布局 Id
     */
    protected abstract @LayoutRes
    int getLayoutId();

    /**
     * 初始化View的代码写在这个方法中
     */
    protected abstract void initView(

    );

    /**
     * 页面事件监听的方法，一般用于ViewModel层转到View层的事件注册
     */
    protected abstract void initViewObservable(

    );

    /**
     * 初始化监听器的代码写在这个方法中
     */
    protected abstract void initListener();

    /**
     * 初始数据的代码写在这个方法中，用于从服务器获取数据
     */
    protected abstract void initData();


    /**
     * 初始化ViewModel的id
     *
     * @return BR的id
     */
    protected abstract int initVariableId();

}
